package vn.com.hung.notetaker.utils;

import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;



public class AutoJTextField extends JTextField implements DocumentListener{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private static enum Mode { INSERT, COMPLETION };
    private char autoChar = ',';
    private Mode mode = Mode.INSERT;
    
    public AutoJTextField() {
        super();
        init();
    }
    public AutoJTextField(int numCol) {
        super(numCol);
        init();
    }
    
    private void init() {
        getDocument().addDocumentListener(this);
        addActionListener(new CommitAction());        
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
          
    }

    @Override
    public void insertUpdate(DocumentEvent ev) {
        if (ev.getLength() != 1) {
            return;
        }
         
        int pos = ev.getOffset();
        String content = null;
        try {
            content = getText(0, pos + 1);
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
         
        // Find where the word starts
        int w;
        for (w = pos; w >= 0; w--) {
            if (! Character.isLetter(content.charAt(w))) {
                break;
            }
        }
        if (pos - w < 2) {
            // Too few chars
            return;
        }
         
        String prefix = content.substring(w + 1).toLowerCase();
        List<String> words = Tags.getTags();
        
        int n = Collections.binarySearch(words, prefix);
        if (n < 0 && -n <= words.size()) {
            String match = words.get(-n - 1);
            if (match.startsWith(prefix)) {
                // A completion is found
                String completion = match.substring(pos - w);
                // We cannot modify Document from within notification,
                // so we submit a task that does the change later
                SwingUtilities.invokeLater(
                        new CompletionTask(completion, pos + 1));
            } else {
                mode = Mode.INSERT;
            }
        } else {
            // Nothing found
            mode = Mode.INSERT;
        }
       
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
         
    }
    private class CompletionTask implements Runnable {
        String completion;
        int position;
         
        CompletionTask(String completion, int position) {
            this.completion = completion;
            this.position = position;
        }
         
        public void run() {
            //tf.insert(completion, position);
            setText(getText() + completion);
            setCaretPosition(position + completion.length());
            moveCaretPosition(position);
            mode = Mode.COMPLETION;
        }
    }
    private class CommitAction extends AbstractAction {
        public void actionPerformed(ActionEvent ev) {
            if (mode == Mode.COMPLETION) {
                int pos = getSelectionEnd();
                setText(getText() + autoChar);
                setCaretPosition(pos + 1);
                mode = Mode.INSERT;
            } else {
                System.out.println("inserting");
                String[] tags = getText().split(",");
                
                for (String tag : tags) {
                    tag = tag.trim();
                    if (tag.length() < 3) {
                        // too short tag
                        continue;
                    }
                   Tags.insertTag(tag);
                }
            }
        }
    }
    
    public void setAutoChar(char c) {
        this.autoChar = c;
    }
    
}
